package com.woniu.serviceprice.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.woniu.internalcommon.constant.CommonStatusEnum;
import com.woniu.internalcommon.dto.ForecastPriceDTO;
import com.woniu.internalcommon.dto.PriceRule;
import com.woniu.internalcommon.dto.ResponseResult;
import com.woniu.internalcommon.response.DirectionResponse;
import com.woniu.internalcommon.response.ForecastPriceResponse;
import com.woniu.internalcommon.util.BigDecimalUtils;
import com.woniu.serviceprice.mapper.PriceRuleMapper;
import com.woniu.internalcommon.remote.ServiceMapClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;

@Service
@Slf4j
public class PriceService {


    @Autowired
    private ServiceMapClient serviceMapClient;

    @Autowired
    private PriceRuleMapper priceRuleMapper;

    /**
     * 计算预估价格
     * @param depLongitude 出发地经度
     * @param depLatitude 出发地纬度
     * @param destLongitude 目的地经度
     * @param destLatitude 目的地纬度
     * @param cityCode 城市编码
     * @param vehicleType 车辆类型
     * @return
     */
    public ResponseResult forecastPrice(String depLongitude, String depLatitude, String destLongitude, String destLatitude,
                                        String cityCode, String vehicleType){

        log.info("出发地经度："+depLongitude);
        log.info("出发地纬度："+depLatitude);
        log.info("目的地经度："+destLongitude);
        log.info("目的地纬度："+destLatitude);

        log.info("调用地图服务，查询距离和时长");
        /* 存入数据(经纬度坐标) */
        ForecastPriceDTO forecastPriceDTO = new ForecastPriceDTO();
        forecastPriceDTO.setDepLongitude(depLongitude);
        forecastPriceDTO.setDepLatitude(depLatitude);
        forecastPriceDTO.setDestLongitude(destLongitude);
        forecastPriceDTO.setDestLatitude(destLatitude);

        /* 存入数据(距离与耗时) */
        ResponseResult<DirectionResponse> direction = serviceMapClient.direction(forecastPriceDTO);
        Integer distance = direction.getData().getDistance();
        Integer duration = direction.getData().getDuration();
        log.info("距离："+distance);
        log.info("时长："+duration);

        log.info(("距离："+distance+",时长："+duration));

        log.info("读取计价规则");

        /* 条件查询 */
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("city_code",cityCode);
        queryWrapper.eq("vehicle_type",vehicleType);
        /* 根据版本降序排列 */
        queryWrapper.orderByDesc("fare_version");

        /* 根据条件查询出来 */
        List<PriceRule> priceRules = priceRuleMapper.selectList(queryWrapper);
        if (priceRules.size() == 0){
            return ResponseResult.fail(CommonStatusEnum.PRICE_RULE_EMPTY.getCode(),CommonStatusEnum.VERIFICATION_CODE_ERROR.getValue());
        }

        /* 取出最新的计价规则 */
        PriceRule priceRule = priceRules.get(0);

        log.info("根据距离、时长和计价规则，计算价格");

        double price = getPrice(distance, duration, priceRule).doubleValue();


        ForecastPriceResponse forecastPriceResponse = new ForecastPriceResponse();
        forecastPriceResponse.setPrice(price);
        forecastPriceResponse.setCityCode(cityCode);
        forecastPriceResponse.setVehicleType(vehicleType);
        forecastPriceResponse.setFareType(priceRule.getFareType());
        forecastPriceResponse.setFareVersion(priceRule.getFareVersion());

        return ResponseResult.success(forecastPriceResponse);
    }

    /**
     * 计算实际价格
     * @param distance
     * @param duration
     * @param cityCode
     * @param vehicleType
     * @return
     */
    public ResponseResult<Double> calculatePrice( Integer distance ,  Integer duration, String cityCode, String vehicleType){
        // 查询计价规则
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("city_code",cityCode);
        queryWrapper.eq("vehicle_type",vehicleType);
        queryWrapper.orderByDesc("fare_version");

        List<PriceRule> priceRules = priceRuleMapper.selectList(queryWrapper);
        /* 判断数据库是否有数据 */
        if (priceRules.size() == 0){
            return ResponseResult.fail(CommonStatusEnum.PRICE_RULE_EMPTY.getCode(),CommonStatusEnum.VERIFICATION_CODE_ERROR.getValue());
        }

        /* 取出最新的计价规则 */
        PriceRule priceRule = priceRules.get(0);

        log.info("根据距离、时长和计价规则，计算价格");

        BigDecimal price = getPrice(distance, duration, priceRule);
        return ResponseResult.success(price);
    }


    /**
     * 根据距离、时长 和计价规则，计算最终价格      ----(该方法以废弃)----
     * @param distance  距离
     * @param duration  时长
     * @param priceRule 计价规则
     * @return
     */
    public double getPrice_AB(Integer distance , Integer duration,PriceRule priceRule){
        /* 初始化价格 */
        double price = 0;

        // 起步价
        double startFare = priceRule.getStartFare();
        price = BigDecimalUtils.add(price,startFare);

        // 里程费
        // 总里程 m
        double distanceMile = BigDecimalUtils.divide(distance,1000);
        // 起步里程
        double startMile = (double)priceRule.getStartMile();
        double distanceSubtract = BigDecimalUtils.substract(distanceMile,startMile);
        // 最终收费的里程数 km
        double mile = distanceSubtract<0?0:distanceSubtract;
        // 计程单价 元/km
        double unitPricePerMile = priceRule.getUnitPricePerMile();
        // 里程价格
        double mileFare = BigDecimalUtils.multiply(mile,unitPricePerMile);
        price = BigDecimalUtils.add(price,mileFare);

        // 时长费
        // 时长的分钟数
        double timeMinute = BigDecimalUtils.divide(duration,60);
        // 计时单价
        double unitPricePerMinute = priceRule.getUnitPricePerMinute();

        // 时长费用
        double timeFare = BigDecimalUtils.multiply(timeMinute,unitPricePerMinute);
        price = BigDecimalUtils.add(price,timeFare);

        BigDecimal priceBigDecimal = new BigDecimal(price);
        priceBigDecimal = priceBigDecimal.setScale(2,BigDecimal.ROUND_HALF_UP);

        return priceBigDecimal.doubleValue();
    }


    /**
     * @Description: 根据距离、时长 和计价规则，计算最终价格
     * @param distance  距离
     * @param duration  时长
     * @param priceRule 计价规则
     * @Author:  zcnovice
     * @date:  2025/7/10 下午6:48
     */

    /* 总价 = 起步价 + (里程 - 起步里程) * 里程单价 + 时长 * 时长单价 */
    public BigDecimal getPrice(Integer distance, Integer duration, PriceRule priceRule) {
        /* 初始化价格 */
        BigDecimal total = new BigDecimal(0);

        /* 总价 = 起步价 */
        BigDecimal startFare = new BigDecimal(priceRule.getStartFare().toString());
        total = total.add(startFare);

        /* 里程计算 */
        //把米装换为公里                                          除以1000，               保留2位小数，       四舍五入
        BigDecimal distanceKm = new BigDecimal(distance).divide(new BigDecimal(1000),2, RoundingMode.HALF_UP);
        //起步里程装换为BigDecimal类型
        BigDecimal startMile = new BigDecimal(priceRule.getStartMile());
        //总里程减去起步里程                                           小于0的话，就返回0，否则返回计算结果
        BigDecimal chargeableMile = distanceKm.subtract(startMile).max(BigDecimal.ZERO);
        //                           收费里程    *     每公里单价
        BigDecimal mileFare = chargeableMile.multiply(new BigDecimal(priceRule.getUnitPricePerMile().toString()));
        /* 总价 = 起步价 + (里程 - 起步里程) * 里程单价 */
        total = total.add(mileFare);

        // 时长计算
        /* 与上面相似，（这里是把秒钟转换为分钟） */
        BigDecimal durationMin = new BigDecimal(duration).divide(new BigDecimal(60), 2, RoundingMode.HALF_UP);
        //  时长*时长单价
        BigDecimal timeFare = durationMin.multiply(new BigDecimal(priceRule.getUnitPricePerMinute().toString()));

        /* 总价 = 起步价 + (里程 - 起步里程) * 里程单价 + 时长 * 时长单价 */
        total = total.add(timeFare);

        // 四舍五入到2位小数
        return total.setScale(2, RoundingMode.HALF_UP);

    }


}
